;> Expr
;lookup takes r10=1st char, r3=2nd char, r4=start of rest, aeline=end
;returns with iacc at dataitem if eq else neq
LOOKUP SUB R1,R10,#"@"
 ADD R0,ARGP,#PROCPTR
 LDR R1,[R0,R1,LSL #2] ;base from VARPTR array
 MOVS R0,R1
 BNE LOOKP1A
LOOKFL TEQ R1,#1
 MOV PC,R14 ;ne
LOOKPY TEQ R4,AELINE
 SUBEQ R0,R0,#2
 MOVEQ PC,R14
LOOKP1 MOVS R0,R1 ;move pointer, end of list?
 BEQ LOOKFL
LOOKP1A LDMIA R0!,{R1,R5} ;link to next field and first 2 characters
 MOV R5,R5,ROR #8
 TEQ R3,R5,LSR #24 ;is it the same?
 BNE LOOKP1 ;no, so try next field
 ANDS R5,R5,#&FF ;end of entry?
 BEQ LOOKPY
 TEQ R4,AELINE ;end of variable?
 BEQ LOOKP1
 LDRB R6,[R4] ;2nd char matches?
 TEQ R6,R5
 BNE LOOKP1
 MOV R2,R4 ;set start pointer
 SUB R0,R0,#2
LOOKP2 LDRB R6,[R2,#1]!
 LDRB R5,[R0],#1
 TEQ R6,R5
 BEQ LOOKP2
 TEQ R5,#0
 BNE LOOKP1
 TEQ R2,AELINE
 BNE LOOKP1
 MOV PC,R14
;create routines for main statement code
GOTLTCREATE BCS DONEXT ;branch directly to DONEXT (ignore LINK!)
 MOV R0,AELINE
GOTLTCREATE1 LDRB R7,[R0],#1
 CMP R7,#" "
 BEQ GOTLTCREATE1
 CMP R7,#"="
 BNE MISTAK
;now fall into create
;create a variable. Input is the failure of lv to find something. Thus we have
;R10=first char of item, R3=second char of item or 0, R4..AELINE other chars
;TYPE contains the number of zero bytes on the end
;result ne, cc, cs as lv
CREATE SUB R0,R10,#"@"
 ADD R0,ARGP,R0,LSL #2
 ADD R0,R0,#PROCPTR ;VARPTR Array
CREALP LDR R1,[R0] ;first find the list end
 TEQ R1,#0
 MOVNE R0,R1 ;not end, continue
 BNE CREALP
 LDR R2,[ARGP,#FSA]
 SUB R1,AELINE,R4
 ADD R1,R1,TYPE
 ADD R1,R1,R2
 ADD R1,R1,#512 ;length+no zeroes+fsa
 CMP R1,SP
 BCS ALLOCR
 STR R2,[R0] ;update list entry
 MOV R1,#0
 STR R1,[R2],#4 ;null pointer on new end
 STRB R3,[R2],#1 ;second character or 0
 TEQ R3,#0
 BEQ CREAND ;early finish
 MOV R3,R4
CREANM TEQ R3,AELINE
 LDRNEB R5,[R3],#1
 STRNEB R5,[R2],#1
 BNE CREANM
 STRB R1,[R2],#1 ;final zero byte
CREAND STMFD SP!,{TYPE}
 CMP TYPE,#256
 MOVCS TYPE,#4 ;ref arrays are integers
 ADDCS AELINE,AELINE,#1 ;and need an extra character to be ignored
 TEQ TYPE,#4 ;word align if integer
 [ FP=1
 TEQNE TYPE,#8 ;word align if floating point
 ]
 ADDEQ R2,R2,#3
 BICEQ R2,R2,#3
 STMFD SP!,{R2}
 TEQ TYPE,#128
 MOVEQ TYPE,#5 ;strings have only 5 bytes in them
 TEQ TYPE,#0 ;put in bytes of zero
CREZER STRNEB R1,[R2],#1
 SUBNES TYPE,TYPE,#1
 BNE CREZER
 ADD R2,R2,#3
 BIC R2,R2,#3
 STR R2,[ARGP,#FSA]
 LDMFD SP!,{IACC,TYPE}
 TEQ TYPE,#225 ;ne status
 MOV PC,R14
CRAELV STMFD SP!,{R14}
 BL AELV
 LDMNEFD SP!,{PC}
 LDMCSFD SP!,{PC} ;return if ne or cs
 BL CREATE
 LDMFD SP!,{PC}
;here before start of statement
CRUNCHSTARTBLANK TST R0,#1
 STREQB R10,[R2],#1 ;keep character if flag not set
CRUNCHSTART LDRB R10,[R1],#1 ;get item
 CMP R10,#" "
 BEQ CRUNCHSTARTBLANK
;first character of statement, character in R10
 CMP R10,#"*"
 CMPNE R10,#TDATA
 BEQ CRUNCHCOPYLINE
;any character of statement
CRUNCHITEMS CMP R10,#" "
 BEQ CRUNCHSPACEINSTMT
;reentry from CRUNCHSPACEINSTMT
CRUNCHNOTSPACE CMP R10,#TREM
 BEQ CRUNCHREMSTMT
 CMP R10,#""""
 BEQ CRUNCHSKIPSTRING
 CMP R10,#":"
 CMPNE R10,#TELSE
 CMPNE R10,#TTHEN
 CMPNE R10,#13
 BEQ CRUNCHENDSTMT
CRUNCHKEEPNOTEND STRB R10,[R2],#1 ;OK: keep it!
 LDRB R10,[R1],#1 ;next character
 B CRUNCHITEMS
CRUNCHENDSTMT TST R0,#8
 BEQ CRUNCHENDSTMT2
 LDRB R5,[R2,#-1] ;check if can eliminate preceeding end of stmt
;note THEN cannot change correctness of program!
 CMP R5,#":"
 SUBEQ R2,R2,#1
CRUNCHENDSTMT2 STRB R10,[R2],#1 ;write to target
 CMP R10,#13 ;end of line?
 BNE CRUNCHSTART ;no: start new statement
 SUB R5,R2,R4
 STRB R5,[R4,#2] ;write new length of line
 MOV R3,#0 ;first line false
 TST R0,#16
 BEQ CRUNCHLINE
 CMP R5,#4
 MOVEQ R2,R4
CRUNCHLINE LDRB R10,[R1],#1 ;move high line number
 STRB R10,[R2],#1
 CMP R10,#255
 MOVEQ PC,R14 ;exit if last line
 LDRB R10,[R1],#2 ;move low line number, moving past length
 STRB R10,[R2],#1
 MOV R10,#0
 STRB R10,[R2],#1 ;zeroing length to stop problems on backwards checks
 SUB R4,R2,#3 ;remember address of start of line
 B CRUNCHSTART
CRUNCHSPACEINSTMT TST R0,#2 ;crunch spaces inside statement?
 BEQ CRUNCHKEEPNOTEND ;no: but have space in hand so efficient dest
CRUNCHLOTS LDRB R10,[R1],#1
 CMP R10,#" "
 BEQ CRUNCHLOTS ;read 'til non-space
 LDRB R5,[R2,#-1] ;get last character from output
;now check if can go together
 CMP R5,#""""
 CMPEQ R5,R10
 BEQ CRUNCHPANIC ;arghh! both quotes
 CMP R5,#"$"
 CMPNE R5,#"%"
 CMPNE R5,#TRND
 BEQ CRUNCHPREVWORRYBKT ;musn't follow with a bracket or a possibly dyadic op
 CMP R5,#TEOR
 CMPNE R5,#TAND
 BEQ CRUNCHPOSTALPHA ;musn't follow with alpha since it confuses assembler
 CMP R10,#"!"
 CMPNE R10,#"?"
 CMPEQ R5,#")"
 BEQ CRUNCHPANIC ;musn't follow ) with ! or ?
 LDRB R6,[R7,R5]
 CMP R6,#0
 CMPNE R5,#"."
 BNE CRUNCHNOTSPACE
;first is 0-9 . A-Z _-z
 LDRB R6,[R7,R10]
 CMP R6,#0
 CMPNE R10,#"." ;musn't connect . to number
 CMPNE R10,#"$" ;musn't move monadic $ from one to another
 BEQ CRUNCHPANIC
CRUNCHPREVWORRYBKT CMP R10,#"(" ;musn't attach a bracket!
 CMPNE R10,#"!" ;musn't make dyadic !
; CMPNE R10,#"|" ;in case of dyadic | break glass
 CMPNE R10,#"?" ;musn't make dyadic ?
 BNE CRUNCHNOTSPACE
;char-char pair problem
CRUNCHPANIC MOV R5,#" "
 STRB R5,[R2],#1 ;insert one space
 B CRUNCHNOTSPACE ;check next character for statement delimiter etc.
CRUNCHPOSTALPHA LDRB R6,[R7,R10]
 CMP R6,#0
 BEQ CRUNCHPANIC
 B CRUNCHNOTSPACE
CRUNCHSKIPSTRING STRB R10,[R2],#1
 LDRB R10,[R1],#1
 CMP R10,#13
 BEQ CRUNCHENDSTMT2
 CMP R10,#""""
 BNE CRUNCHSKIPSTRING
 B CRUNCHKEEPNOTEND
CRUNCHREMSTMT TEQ R3,#1
 TSTNE R0,#4
 BEQ CRUNCHCOPYLINE ;on first line or flag not set
CRUNCHREM LDRB R10,[R1],#1
 CMP R10,#13
 BNE CRUNCHREM
 B CRUNCHENDSTMT
CRUNCHCOPYLINE STRB R10,[R2],#1
 LDRB R10,[R1],#1
 CMP R10,#13
 BNE CRUNCHCOPYLINE
 B CRUNCHENDSTMT2
;r0=bit mask for crunching
;r1=start of item to crunch [will return r2=end of item]
CRUNCHROUTINE MOV R2,R1 ;destination of crunched stuff
 MOV R3,#1 ;first line true
 LDRB R10,[R1],#1 ;move newline
 STRB R10,[R2],#1
 ADR R7,LVTABLE
 B CRUNCHLINE
LVTABLE = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,128,4,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = 0,0,0,0,0,0,0,0,0,0,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 = 0,0,0,0,0,0,0,0,0,0,0,TFPLV,TFPLV,TFPLV,TFPLV,0
 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 = 0,0,0,0,0,0,0,0,0,0,0,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
 = TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV,TFPLV
AELV MOV AELINE,LINE
LVBLNK LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ LVBLNK
;LV reads the l value of the current item if possible.

;If LV reads an l value IACC will be the address of the data byte(s) {or string
;control block} and there will be an NEQ status
;TYPE will be 0 for byte, 4 for integer and 5 for a floating point variable
;TYPE will be 129 for $<factor> and 128 for ordinary strings.
;If it is a reference to an array then TYPE will be 256+ expected value.

;If there is an EQ status then if the carry is set it is silly else if the
;carry is clear it is not in the list.

LVCONT AND R1,AELINE,#CACHEMASK
 ADD R1,ARGP,R1,LSL #CACHESHIFT
 LDMIA R1,{IACC,R1,R4,TYPE}
 CMP R4,AELINE
 BNE LVNOTCACHE
 ADDS AELINE,AELINE,R1
 MOVPL PC,R14
 BIC AELINE,AELINE,#TFP
 B ARLOOKCACHE
LVNOTCACHE MOV R4,AELINE
 SUBS R1,R10,#"@" ;renorm for varptr array reference
 BLS LVFD ;probably not an lv but check for unary things and @%
;this test also removes numeric first characters
 ADR R3,LVTABLE
 LDRB TYPE,[R3,R10]
 CMP TYPE,#0
 BNE LVFLOATIND
MULTI LDRB R5,[AELINE],#1
 LDRB TYPE,[R3,R5]
 CMP TYPE,#0
 BEQ MULTI
 CMP TYPE,#TFPLV
 LDRNEB R5,[AELINE],#1
 CMP R5,#"("
 BEQ BKTVAR
 SUB AELINE,AELINE,#1 ;OK: normal variable
 ADD R3,ARGP,#PROCPTR
 LDR R1,[R3,R1,LSL #2] ;base from VARPTR array
 EORS R3,R4,AELINE ;No more chars? :provides 0 in R3 for single char create
 BEQ LOOKU5 ;Branch if no more
 LDRB R3,[R4],#1 ;if more chars R3 is next char
 CMP R10,#"Z"+1
 CMPCC R3,#"%"
 BEQ LVSTATICINT
LOOKU1 MOVS R0,R1 ;pointer in different register
 BEQ LVNTFN ;end of list
 LDMIA R0!,{R1,R5} ;R1=link to next field, R5=first 4 characters
 MOV R5,R5,ROR #8 ;Move first character to top of R5
 TEQ R3,R5,LSR #24 ;Do quick check on first character
 BNE LOOKU1
 TEQ R4,AELINE
 BEQ LOOKA2 ;Branch if run out of length
 MOV R6,R4
LOOKU2 MOV R5,R5,ROR #8 ;Move current character to top of R5
 LDRB R2,[R6],#1 ;Get variable character
 TEQ R2,R5,LSR #24 ;Unless equal, give up
 BNE LOOKU1
 TEQ R6,AELINE ;Branch if run out of length
 BEQ LOOKA1
 MOV R5,R5,ROR #8 ;Move current character to top of R5
 LDRB R2,[R6],#1 ;Get variable character
 TEQ R2,R5,LSR #24 ;Unless equal, give up
 BNE LOOKU1
 TEQ R6,AELINE ;Branch if run out of length
 BEQ LOOKA0
 MOV R5,R5,ROR #8 ;Move current character to top of R5
 LDRB R2,[R6],#1 ;Get variable character
 TEQ R2,R5,LSR #24 ;Unless equal, give up
 BNE LOOKU1
 LDR R5,[R0],#4 ;Get next word of list entry
 TEQ R6,AELINE ;Branch if run out of length
 BEQ LOOKA3
 MOV R5,R5,ROR #8 ;Move current character to top of R5
 LDRB R2,[R6],#1 ;Get variable character
 TEQ R2,R5,LSR #24 ;Unless equal, give up
 BNE LOOKU1
 TEQ R6,AELINE ;Loop if not run out of length
 BNE LOOKU2
 SUB R0,R0,#2
LOOKA0 ADD R0,R0,#1 ;adjust by 0
LOOKA1 ADD R0,R0,#1 ;adjust by -1
LOOKA2 ADD R0,R0,#1 ;adjust by -2
LOOKA3 TST R5,#&FF ;Check list entry has ended
 BNE LOOKU1 ;Otherwise loop
 TEQ TYPE,#4 ;found
 [ FP=1
 TEQNE TYPE,#8
 ]
 SUBNE R0,R0,#3 ;adjust by -3 but add 3 if type=4, 8
 BICEQ R0,R0,#3 ;final part of word align if type=4, 8
 SUB R4,R4,#1
 B CHKQUE
LOOKU5 MOVS R0,R1 ;pointer in different register
 BEQ LVNTFN ;end of list
 LDMIA R0!,{R1,R5} ;R1=link to next field, R5=first 4 characters
 TST R5,#&FF ;Is this the correct entry?
 BNE LOOKU5 ;Loop if not
 TEQ TYPE,#4
 [ FP=1
 TEQ TYPE,#8
 ]
 SUBNE R0,R0,#3 ;adjust by -3
CHKQUE LDRB R10,[AELINE]
 TEQ R10,#"!"
 BEQ BIPLIN
 EORS R1,R10,#"?"
 BEQ BIQUER
 AND R1,R4,#CACHEMASK
 ADD R1,ARGP,R1,LSL #CACHESHIFT
 SUB R2,AELINE,R4
 STMIA R1,{IACC,R2,R4,TYPE}
 MOVNE PC,R14 ;ne status
LVSTATICINT ADD IACC,ARGP,#INTVAR
 SUB R1,R10,#"@"
 ADD IACC,IACC,R1,LSL #2
 SUB R4,R4,#1
 B CHKQUE
LVFLOATIND CMP R10,#"|"
 BNE LVFD
 MOV R1,#TFPLV
 B UNQUER
LVNTFN ADDS R0,R0,#0
 TEQ R0,R0
 MOV PC,R14 ;eq, cc
BIPLIN MOV R1,#4
BIQUER STMFD SP!,{R1,R14}
 ADD AELINE,AELINE,#1
 BL VARIND
 BL INTEGY
 STMFD SP!,{IACC}
 BL FACTOR
 BL INTEGZ
 LDMFD SP!,{R1}
 ADD IACC,IACC,R1
 LDMFD SP!,{TYPE,R14}
 CMP TYPE,#6 ;ne status
 MOV PC,R14
LVFDAT LDRB R5,[AELINE],#1
 CMP R5,#"%"
 BNE LVFDC1
 LDRB R0,[AELINE]
 CMP R0,#"("
 BEQ LVFDC1
 MOV TYPE,#4 ;built in integer
 ADD IACC,ARGP,#INTVAR
 B CHKQUE
LVFD BEQ LVFDAT
 CMP R10,#"!"
 BEQ UNPLIN
 MOV R1,#129
 CMP R10,#"$"
 BEQ UNQUER
 EORS R1,R10,#"?"
 BEQ UNQUER
 CMP R10,R10
 MOV PC,R14 ;eq,cs
LVFDC1 SUB AELINE,AELINE,#1
 CMP R10,R10
 MOV PC,R14
UNPLIN MOV R1,#4
UNQUER STMFD SP!,{R1,R14}
 BL FACTOR
 BL INTEGZ
 LDMFD SP!,{TYPE,R14}
 CMP TYPE,#6 ;ne status
 MOV PC,R14
BKTVAR LDRB R3,[R4],#1
 ADD R0,ARGP,#PROCPTR
 LDR R1,[R0,R1,LSL #2] ;base from VARPTR array
ARLOOKP1 MOVS R0,R1 ;move pointer, end of list?
 BEQ ARNOTFOUND
 LDMIA R0!,{R1,R5} ;link to next field and first 2 characters
 MOV R5,R5,ROR #8
 TEQ R3,R5,LSR #24 ;is it the same?
 BNE ARLOOKP1 ;no, so try next field
 ANDS R5,R5,#&FF ;end of entry?
 BEQ ARLOOKPY
 TEQ R4,AELINE ;end of variable?
 BEQ ARLOOKP1
 LDRB R6,[R4] ;2nd char matches?
 TEQ R6,R5
 BNE ARLOOKP1
 MOV R2,R4 ;set start pointer
 SUB R0,R0,#2
ARLOOKP2 LDRB R6,[R2,#1]!
 LDRB R5,[R0],#1
 TEQ R6,R5
 BEQ ARLOOKP2
 TEQ R5,#0
 BNE ARLOOKP1
 TEQ R2,AELINE
 BNE ARLOOKP1
 B ARLOOKPZ
ARNOTFOUND LDRB R0,[AELINE]
 CMP R0,#")"
 BNE ERARRY
 ORR TYPE,TYPE,#256
 B LVNTFN
ARLOOKPY TEQ R4,AELINE
 BNE ARLOOKP1 ;no need to SUB R0,R0,#2 because of next word align
ARLOOKPZ ADD IACC,IACC,#3
 BIC IACC,IACC,#3
 SUB R4,R4,#1
 AND R1,R4,#CACHEMASK
 ADD R1,ARGP,R1,LSL #CACHESHIFT
 SUB R2,AELINE,R4
 ADD R2,R2,#TFP
 STMIA R1,{IACC,R2,R4,TYPE}
ARLOOKCACHE LDRB R1,[AELINE]
 CMP R1,#")"
 BEQ ARRAYREF
 LDR IACC,[IACC]
 CMP IACC,#16
 BCC ERARRZ
 STMFD SP!,{IACC,TYPE,R14}
 BL EXPR
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BLMI SFIX
 LDMFD SP!,{R4} ;pull address of limit list
 LDR R3,[R4],#4 ;get first limit
 CMP IACC,R3
 BCS ERRSUB
 CMP R10,#")"
 BEQ ARREND
 CMP R10,#","
 BNE ERBRA
 MOV R5,#0
ARLOP ADD IACC,R5,IACC ;add expr to acc
 LDR R6,[R4] ;multiply by next limit
 MUL R5,R6,IACC
 STMFD SP!,{R4,R5}
 BL EXPR
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BLMI SFIX
 LDMFD SP!,{R4,R5}
 LDR R3,[R4],#4
 CMP IACC,R3
 BCS ERRSUB
 CMP R10,#","
 BEQ ARLOP
 ADD R5,R5,IACC
 CMP R10,#")"
 BNE ERBRA
 MOV IACC,R5
ARREND LDR R3,[R4],#8 ;step past number of entries
 TEQ R3,#0
 BNE ERRSB2
 MOV R1,IACC,LSL #2 ;multiply by 4
 LDMFD SP!,{TYPE,R14}
 [ FP=0
 CMP TYPE,#5
 ADDCS R1,R1,IACC ;multiply by 5 for type=5 and 128
 |
 CMP TYPE,#8
 ADDHI R1,R1,IACC ;type >8 then *5
 MOVEQ R1,IACC,LSL #3 ;multiply by 8
 ]
 ADD IACC,R1,R4
 LDRB R10,[AELINE]
 TEQ R10,#"!"
 BEQ BIPLIN
 EORS R1,R10,#"?"
 MOVNE PC,R14 ;ne status
 B BIQUER
ARRAYREF ORRS TYPE,TYPE,#256
 ADD AELINE,AELINE,#1
 MOV PC,R14
PUSHTYPE TEQ TYPE,#0
 BMI FPUSH
 STMNEFD SP!,{IACC}
 MOVNE PC,R14
;push string to stack. Uses r0,r1,clen,r3,r4
SPUSH ADD R0,ARGP,#STRACC
 SUBS R1,CLEN,R0
 BEQ SPUSHX
SPUSHLARGE ADD R1,R1,#3
 BIC R1,R1,#3
 SUB SP,SP,R1
 MOV R3,SP
SPUSHL LDR R4,[R0],#4
 STR R4,[R3],#4
 SUBS R1,R1,#4
 BNE SPUSHL
SPUSHX STMFD SP!,{CLEN}
 MOV PC,R14
FPUSH
 [ FP=0
 ORR FGRD,FSIGN,FACCX
 STMFD SP!,{FACC,FGRD}
 |
 FPUSH
 ]
 MOV PC,R14
PULLTYPE LDMFD SP!,{TYPE}
 TEQ TYPE,#0
 BMI FPULL
 LDMNEFD SP!,{IACC}
 MOVNE PC,R14
SPULL LDMFD SP!,{CLEN}
 ADD R0,ARGP,#STRACC
 SUBS R1,CLEN,R0
 MOVEQ PC,R14 ;return quickly if zero length string
 ADD R1,R1,#3
 BIC R1,R1,#3
SPULLL LDR R3,[SP],#4
 STR R3,[R0],#4
 SUBS R1,R1,#4
 BNE SPULLL
 MOV PC,R14
;load fp acc from stack
FPULL
 [ FP=0
 LDMFD SP!,{FACC,FACCX}
 AND FSIGN,FACCX,#&80000000
 AND FACCX,FACCX,#255
 |
 LDFD FACC,[SP],#8
 ]
 MOV PC,R14
DIVOP STMFD SP!,{R14}
 BL INTEGY
 STMFD SP!,{IACC}
 BL EXPRRECUR
 BL INTEGY
 LDMFD SP!,{R4,R14}
;integer divide r4 by iacc; div result in facc, mod result in r4
;uses r1,r2,r3,r5,r7
INTDIV EOR R3,IACC,R4 ;result sign for DIV
 MOVS R7,R4 ;result sign for REM
 RSBMI R4,R4,#0
 MOVS R2,IACC
 BEQ ZDIVOR
 RSBMI R2,R2,#0
 MOV R6,R2
 MOV IACC,#0
 CMP R6,R4,LSR #1
DIVJUS MOVLS R6,R6,LSL #1
 CMPLS R6,R4,LSR #1
 BLS DIVJUS
DIVER CMP R4,R6
 SUBCS R4,R4,R6
 ADC IACC,IACC,IACC
 MOV R6,R6,LSR #1
 CMP R6,R2
 BCS DIVER
 TEQ R3,#0
 RSBMI IACC,IACC,#0
 TEQ R7,#0
 RSBMI R4,R4,#0
 MOV PC,R14
COMPR TEQ TYPE,#0
 BEQ STNCMP
 BMI FCOMPR
 STMFD SP!,{R14,R7,IACC}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FCOMPS
 LDMFD SP!,{R14,R7,R1}
 CMP R1,IACC
 MOV IACC,#0 ;initial FALSE
 MOV PC,R14
 [ FP=0
FCOMPS LDMFD SP!,{R4}
 STMFD SP!,{FACC,FACCX,FSIGN}
 MOV FACC,R4
 BL IFLT
 BL FTOW
 LDMFD SP!,{FACC,FACCX,FSIGN}
 B FCOMPT
FCOMPR STMFD SP!,{R14,R7,FACC,FACCX,FSIGN}
 BL EXPRRECUR ;R5
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BLPL IFLT
 LDMFD SP!,{FWACC,FWACCX,FWSIGN} ;get first
FCOMPT MOV TYPE,#TINTEGER
 CMP FWSIGN,FSIGN ;only top bits may be set!
 BNE FCOMPRX ;easy: signs different
 TEQ FSIGN,#0
 BMI FCMPNE
;signs same and positive
 CMP FWACCX,FACCX
 MOVNE IACC,#0
;exit if exponents different
 LDMNEFD SP!,{R7,PC}
;equal case: a simple CMP FWACC,FACC would suffice for all except comparison
;of 2E-39 with 0: numbers whose exponent are 0 have problems being compared
;with 0 since the mantissa is effectively negative - fine if being compared
;with another negative mantissa, but lousy against 0 with its zero mantissa
 CMP FACCX,#0
 BEQ FCOMPZE
;simple case - neither number has zero exponent (and therefore isn't 0)
 CMP FWACC,FACC
 MOV IACC,#0
 LDMFD SP!,{R7,PC}
;both positive and both zero exponent
FCOMPZE TEQ FACC,#0
 TEQNE FWACC,#0
 BEQ FCOMPZZ ;one or the other is zero, so compare the other way round...
 CMP FWACC,FACC
 MOV IACC,#0
 LDMFD SP!,{R7,PC}
;same signs and negative
FCMPNE CMP FACCX,FWACCX
;unlike the positive case, can get away with this, since 0 isn't negative
FCOMPZZ CMPEQ FACC,FWACC
FCOMPRX MOV IACC,#0
 LDMFD SP!,{R7,PC}
 |
FCOMPS LDMFD SP!,{R4}
 FLTD F1,R4 ;float first number
 B FCOMPT
FCOMPR STMFD SP!,{R14,R7}
 FPUSH
 BL EXPRRECUR ;R5
 TEQ TYPE,#0
 BEQ ERTYPEINT
 FLTPLD FACC,IACC ;float if rqd
 LDFD F1,[SP],#8 ;get first
FCOMPT MOV TYPE,#TINTEGER
 CMF F1,FACC
 MOV IACC,#0
 LDMFD SP!,{R7,PC}
 ]
STNCMP STMFD SP!,{R7,R14}
 BL SPUSH ;preserves R5
 BL EXPRRECUR ;R5
 TEQ TYPE,#0
 BNE ERTYPESTR
 LDMFD SP!,{R0}
 MOV TYPE,CLEN
 CMP CLEN,R0
 MOVCS CLEN,R0 ;clen becomes shortest length
 ADD R1,ARGP,#STRACC
 SUB R3,R0,R1
 ADD R3,R3,#3
 BIC R3,R3,#3
 MOV R5,SP
COMPRG CMP CLEN,R1
 BEQ COMPRH
 LDRB R6,[R1],#1
 LDRB R7,[R5],#1 ;first string
 CMP R7,R6
 BEQ COMPRG
COMPRH CMPEQ R0,TYPE ;skip if fall through
 ADD SP,SP,R3
 MOV IACC,#0
 MOV TYPE,#TINTEGER
 LDMFD SP!,{R7,PC}
;Expr reads a right hand side with AELINE.
;TYPE contains the type. It can be examined by TEQ TYPE,#0:
;        If eq it read a string
;        if NE and plus it read an integer word (IN FACC)
;        if NE and minus it read fp
;R10 contains the next character, which has been read (unlike 6502 one)
AEEXPR MOV AELINE,LINE
EXPR STMFD SP!,{R14} ;save link
 BL FACTOR
EXPRBLNK LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ EXPRBLNK
 ADR R4,PRIORTABLE
 LDR R10,[R4,R10,LSL #2]
 CMP R10,#256
 LDMCCFD SP!,{PC}
 MOV R7,#0 ;expression a tough one after all!
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
;Needs R10 to be pending priority<<24
EXPRRECUR MOV R7,R10,LSR #28
 STMFD SP!,{R7,R14}
 BL FACTOR
 LDMFD SP!,{R7}
EXPRBLNK1 LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ EXPRBLNK1
EXPRNEXT ADR R4,PRIORTABLE
 LDR R10,[R4,R10,LSL #2]
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R10<256
EXPRHARD ADD PC,PC,R10,LSL #2 ;and go there
AJ7 * .+4
EXPRNEQUAL BL COMPR
 MVNNE IACC,#0
 B EXPRNONRIGHT
EXPROR BL INTEGY
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 ORR IACC,IACC,R1
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC}
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
EXPREOR BL INTEGY
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 EOR IACC,IACC,R1
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC}
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
EXPRAND BL INTEGY
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 AND IACC,IACC,R1
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC}
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
EXPRLT LDRB R4,[AELINE],#1
 CMP R4,#"="
 BEQ EXPRLTOREQ
 CMP R4,#">"
 BEQ EXPRNEQUAL
 CMP R4,#"<"
 BEQ EXPRLSHIFT
 SUB AELINE,AELINE,#1
 BL COMPR
 MVNLT IACC,#0 ;test for less than
;Special code to stop priority 3 operations doing left to right
EXPRNONRIGHT TST R10,#&10000000
 MOVNE R10,R10,LSR #25 ;rebuild operator
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R10<256)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2 ;ok, go ahead
EXPRLTOREQ BL COMPR
 MVNLE IACC,#0 ;test for less than or equal
 B EXPRNONRIGHT
EXPREQ BL COMPR
 MVNEQ IACC,#0
 B EXPRNONRIGHT
EXPRGT LDRB R4,[AELINE],#1
 CMP R4,#"="
 BEQ EXPRGTOREQ ;distant
 CMP R4,#">"
 BEQ EXPRRSHIFT ;distant
 SUB AELINE,AELINE,#1
 BL COMPR
 MVNGT IACC,#0 ;test for greater than
 B EXPRNONRIGHT
EXPRGTOREQ BL COMPR
 MVNGE IACC,#0
 B EXPRNONRIGHT
EXPRRSHIFT BL INTEGY
 STMFD SP!,{IACC,R7}
 LDRB R4,[AELINE],#1
 CMP R4,#">"
 BEQ EXPRRSHIFTLOGICAL
 SUB AELINE,AELINE,#1
 BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 MOV IACC,R1,ASR IACC
 B EXPRNONRIGHT
EXPRRSHIFTLOGICAL BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 MOV IACC,R1,LSR IACC
 B EXPRNONRIGHT
EXPRADD TEQ TYPE,#0
 BEQ STNCON
 BMI FPLUS
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FPLUST
 LDMFD SP!,{R1,R7}
 ADD IACC,IACC,R1
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
 [ FP=0
FPLUS STMFD SP!,{FACC,FACCX,FSIGN,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BLPL FLOATQ
FPLUSS LDMFD SP!,{FWACC,FWACCX,FWSIGN}
 TEQ FWACC,#0
 BLNE FADDW
 |
FPLUS STMFD SP!,{R7}
 FPUSH
 BL EXPRRECUR
 TEQ TYPE,#0
 BEQ ERTYPEINT
 FLTPLD FACC,IACC
 LDFD F1,[SP],#8
 MOV TYPE,#TFP
FPLUSS ADFD FACC,FACC,F1
 ]
EXPRPULLNEXT LDMFD SP!,{R7}
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC}
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
 [ FP=0
FMINUT TEQ FACC,#0
 EORNE FSIGN,FSIGN,#&80000000
FPLUST LDMFD SP!,{FWACC}
 STMFD SP!,{FACC,FACCX,FSIGN}
 MOV FACC,FWACC
 BL IFLT ;no need to change type
 B FPLUSS
FMINUS STMFD SP!,{FACC,FACCX,FSIGN,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BLPL FLOATQ
 TEQ FACC,#0
 EORNE FSIGN,FSIGN,#&80000000
 B FPLUSS
 |
FPLUST LDMFD SP!,{IACC}
 FLTD F1,IACC ;no need to change type
 B FPLUSS
FMINUT LDMFD SP!,{IACC}
 FLTD F1,IACC
 SUFD FACC,F1,FACC
 B EXPRPULLNEXT
FMINUS STMFD SP!,{R7}
 FPUSH
 BL EXPRRECUR
 TEQ TYPE,#0
 BEQ ERTYPEINT
 FLTPLD FACC,IACC
 LDFD F1,[SP],#8
 SUFD FACC,F1,FACC
 MOV TYPE,#TFP
 B EXPRPULLNEXT
 ]
EXPRSUB TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FMINUS ;distant
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FMINUT ;distant
 LDMFD SP!,{R1,R7}
 SUB IACC,R1,IACC
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
EXPRMUL TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FTIME
 RSBS R1,IACC,#&B500 ;range of +-SQR(&7fffffff) (minus a bit to be a constant)
 CMNGE IACC,#&B500
 BLT FTIMF
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BEQ ERTYPEINT
 BMI FTIMET
 RSBS R1,IACC,#&B500
 CMNGE IACC,#&B500
 BLT FTIMEL
 LDMFD SP!,{R4,R7}
 MUL IACC,R4,IACC
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
 [ FP=0
FTIMEL BL FLOATB
FTIMET LDMFD SP!,{FWACC}
 STMFD SP!,{FACC,FACCX,FSIGN}
 MOV FACC,FWACC
 BL FLOATB
 B FTIMES
FTIMF BL IFLT
FTIME STMFD SP!,{FACC,FACCX,FSIGN,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BLPL FLOATQ
FTIMES LDMFD SP!,{FWACC,FWACCX,FWSIGN}
 TEQ FACC,#0
 BLNE FMUL0
 |
FTIMEL FLTD FACC,IACC
FTIMET LDMFD SP!,{R4}
 FLTD F1,R4
 B FTIMES
FTIMF FLTD FACC,IACC
FTIME STMFD SP!,{R7}
 FPUSH
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BEQ ERTYPEINT
 FLTPLD FACC,IACC
 LDFD F1,[SP],#8
FTIMES MUFD FACC,F1,FACC
 MOV TYPE,#TFP
 ]
 LDMFD SP!,{R7}
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
 [ FP=0
EXPRDIV BL FLOATY
 STMFD SP!,{FACC,FACCX,FSIGN,R7}
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BLPL FLOATQ
 TEQ FACC,#0
 BEQ ZDIVOR
 LDMFD SP!,{FWACC,FWACCX,FWSIGN}
 BL FXDIV0
 |
EXPRDIV TEQ TYPE,#0
 BLPL FLOATQ
 STMFD SP!,{R7}
 FPUSH
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BLPL FLOATQ
 CMF FACC,#0
 BEQ ZDIVOR
 LDFD F1,[SP],#8
 DVFD FACC,F1,FACC
 ]
 LDMFD SP!,{R7}
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
EXPRINTDIV STMFD SP!,{R7}
 BL DIVOP
 LDMFD SP!,{R7}
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 ADR R4,AJ7
 ADD PC,R4,R10,LSL #2
;The Expression priority table. Each word contains the address of the
;token and the priority. The following information is present:
;token priority
; OR      1
;EOR      1
;AND      2
;  <      3
;  =      3
;  >      3
;  +      4
;  -      4
;  *      5
;  /      5
;DIV      5
;MOD      5
;  ^      6
;All the rest is the value itself.
PRIORTABLE & &00,&01,&02,&03,&04,&05,&06,&07,&08,&09,&0A,&0B,&0C,&0D,&0E,&0F
 & &10,&11,&12,&13,&14,&15,&16,&17,&18,&19,&1A,&1B,&1C,&1D,&1E,&1F
 & &20,&21,&22,&23,&24,&25,&26,&27,&28,&29
 & &A0000000+(EXPRMUL-AJ7)/4
 & &80000000+(EXPRADD-AJ7)/4,&2C
 & &80000000+(EXPRSUB-AJ7)/4,&2E
 & &A0000000+(EXPRDIV-AJ7)/4
 & &30,&31,&32,&33,&34,&35,&36,&37,&38,&39,&3A,&3B
 & &78000000+(EXPRLT-AJ7)/4 ;special bit for relations
 & &7A000000+(EXPREQ-AJ7)/4
 & &7C000000+(EXPRGT-AJ7)/4,&3F
 & &40,&41,&42,&43,&44,&45,&46,&47,&48,&49,&4A,&4B,&4C,&4D,&4E,&4F
 & &50,&51,&52,&53,&54,&55,&56,&57,&58,&59,&5A,&5B,&5C,&5D
 & &C0000000+(EXPRPOW-AJ7)/4,&5F
 & &60,&61,&62,&63,&64,&65,&66,&67,&68,&69,&6A,&6B,&6C,&6D,&6E,&6F
 & &70,&71,&72,&73,&74,&75,&76,&77,&78,&79,&7A,&7B,&7C,&7D,&7E,&7F
 & &40000000+(EXPRAND-AJ7)/4
 & &A0000000+(EXPRINTDIV-AJ7)/4
 & &20000000+(EXPREOR-AJ7)/4
 & &A0000000+(EXPRMOD-AJ7)/4
 & &20000000+(EXPROR-AJ7)/4,&85,&86,&87,&88,&89,&8A,&8B,&8C,&8D,&8E,&8F
 & &90,&91,&92,&93,&94,&95,&96,&97,&98,&99,&9A,&9B,&9C,&9D,&9E,&9F
 & &A0,&A1,&A2,&A3,&A4,&A5,&A6,&A7,&A8,&A9,&AA,&AB,&AC,&AD,&AE,&AF
 & &B0,&B1,&B2,&B3,&B4,&B5,&B6,&B7,&B8,&B9,&BA,&BB,&BC,&BD,&BE,&BF
 & &C0,&C1,&C2,&C3,&C4,&C5,&C6,&C7,&C8,&C9,&CA,&CB,&CC,&CD,&CE,&CF
 & &D0,&D1,&D2,&D3,&D4,&D5,&D6,&D7,&D8,&D9,&DA,&DB,&DC,&DD,&DE,&DF
 & &E0,&E1,&E2,&E3,&E4,&E5,&E6,&E7,&E8,&E9,&EA,&EB,&EC,&ED,&EE,&EF
 & &F0,&F1,&F2,&F3,&F4,&F5,&F6,&F7,&F8,&F9,&FA,&FB,&FC,&FD,&FE,&FF
EXPRMOD STMFD SP!,{R7}
 BL DIVOP
 MOV IACC,R4
 LDMFD SP!,{R7}
 CMP R7,R10,LSR #28
 LDMCSFD SP!,{PC} ;musn't do operation at the moment (also exits if R5=0)
 B EXPRHARD
EXPRLSHIFT BL INTEGY
 STMFD SP!,{IACC,R7}
 BL EXPRRECUR ;R10
 BL INTEGY
 LDMFD SP!,{R1,R7}
 MOV IACC,R1,LSL IACC
 B EXPRNONRIGHT
EXPRPOW STMFD SP!,{R7}
 [ FP=0
 BL FLOATY
 FPUSH
 BL FACTOR ;shortcut!
 BEQ ERTYPEINT
 BPL INTPOW
 CMP FACCX,#&87
 BCS FPOWA ;abs(n)>=64
 BL FFRAC
 TEQ FACC,#0
 BNE FPOWE
IPOW FLDA SP
 MOV TYPE,FWGRD
 BL FIPOW
 PULLJ 2
POWEREND LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ POWEREND
 MOV TYPE,#TFP
 LDMFD SP!,{R7}
 B EXPRNEXT
INTPOW CMP FACC,#64
 MOV FWGRD,FACC
 BCC IPOW
 CMN FACC,#64
 BCS IPOW
 BL FLOATB
FPOWA FPUSH
 BL FONE
 B FPOWC
FPOWE FPUSH ;push fraction
 ADD TYPE,SP,#8
 FLDA TYPE
 MOV TYPE,FWGRD
 BL FIPOW ;compute integer power of input
FPOWC FPUSH ;multiplier
 ADD TYPE,SP,#16
 FLDA TYPE
 BL FLOG ;ln(arg1)
 ADD TYPE,SP,#8
 BL FMUL ;arg2*ln(arg1)
 BL FEXP ;exp(arg2*ln(arg1))
 MOV TYPE,SP
 BL FMUL
 PULLJ 6
 B POWEREND
 |
 BL FLOATY
 FPUSH
 BL FACTOR ;shortcut!
 BEQ ERTYPEINT
 FLTPLD FACC,IACC
 LDFD F1,[SP],#8
 POWD FACC,F1,FACC
POWEREND LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ POWEREND
 MOV TYPE,#TFP
 LDMFD SP!,{R7}
 B EXPRNEXT
 ]
STNCON STMFD SP!,{R7}
 BL SPUSH
 BL EXPRRECUR ;R10
 TEQ TYPE,#0
 BNE ERTYPESTR
;concatenate string on stack before string in buffer
 LDMFD SP!,{R7} ;get length of other string
 ADD R3,ARGP,#STRACC
 SUBS R7,R7,R3
 BEQ EXPRPULLNEXT ;if first string empty then done
 ADD R6,R7,CLEN ;total length
 ADD R4,R3,#256
 CMP R6,R4
 BCS ERLONG
 MOV R4,R6
STNCMV CMP CLEN,R3
 BEQ STNCPL
 LDRB R0,[CLEN,#-1]! ;move second string to end of stracc
 STRB R0,[R4,#-1]!
 B STNCMV
STNCPL SUBS R7,R7,#4
 BCC STNCPP ;less than a word to pull
 LDR R0,[SP],#4
 STR R0,[R3],#4
 B STNCPL
STNCPP MOV CLEN,R6 ;total length
 CMN R7,#4
 BEQ EXPRPULLNEXT ;no fractional word
 LDR R0,[SP],#4 ;last word of all
 STRB R0,[R3],#1
 CMN R7,#3
 BEQ EXPRPULLNEXT
 MOV R0,R0,LSR #8
 STRB R0,[R3],#1
 CMN R7,#2
 BEQ EXPRPULLNEXT
 MOV R0,R0,LSR #8
 STRB R0,[R3],#1
 B EXPRPULLNEXT ;must be this last one
AECHAN MOV AELINE,LINE
CHAN LDRB R10,[AELINE],#1
 CMP R10,#" "
 BEQ CHAN
 CMP R10,#"#"
 BNE CHANNE
CHANNL STMFD SP!,{R14}
 BL FACTOR
 BL INTEGZ
 MOV R1,IACC ;right reg for most swi's
 LDMFD SP!,{PC}
 LNK Factor
